#include "stdafx.h"
#include "audPinIn.h"
#include "..\..\include\imp_typedefine.h"
#include "..\..\include\imp_io_wrapper.h"
#include "..\..\include\imp_timer_wrapper.h"

static int gSize = 0;

CMiiAudPinIn::CMiiAudPinIn(CBaseFilter *pFilter, CCritSec *pLock, HRESULT *phr) : CBaseInputPin(NAME("CPinIn"), pFilter, pLock, phr, L"MiiShow input")
, m_bCopy(false)
, m_nSourcIndex(0)
{
	ZeroMemory(&m_tType, sizeof(m_tType));
	mOutMax  = 2048;
	for(int i=0; i<BUF_NUM; i++){
		m_pBuffer[i] = new char[mOutMax];
		m_lock[i] = CreateEvent( NULL, FALSE, TRUE, NULL );
	}
	m_nBufIndex = 0;
	m_Pos = 0;
}

CMiiAudPinIn::~CMiiAudPinIn()
{
	for(int i=0; i<BUF_NUM; i++){
		delete []m_pBuffer[i];
		CloseHandle(m_lock[i]);
	}
}

HRESULT CMiiAudPinIn::CompleteConnect(IPin *pReceivePin)
{
	return S_OK;
}

HRESULT CMiiAudPinIn::SetMediaType(const CMediaType *pmt)
{
	WAVEFORMATEX  * pvih;
	if(pmt->pbFormat){
		pvih = (WAVEFORMATEX *)pmt->pbFormat;
		memcpy(&m_vInfo, pvih, sizeof(m_vInfo));
	}
	return S_OK;
}

HRESULT CMiiAudPinIn::CheckConnect(IPin *)
{
	return S_OK;
}

HRESULT CMiiAudPinIn::CheckMediaType(const CMediaType *pmt)
{
	return S_OK;
}

HRESULT CMiiAudPinIn::GetMediaType(int iPosition, CMediaType *pMediaType)
{
	if (iPosition < 0)
	{
		return E_INVALIDARG;
	}

	if (!m_tType.IsValid())
	{
		return VFW_S_NO_MORE_ITEMS;
	}
	
	if (iPosition > 0)
	{
		return VFW_S_NO_MORE_ITEMS;
	}

	if (pMediaType)
	{
		CopyMediaType(pMediaType, &m_tType);
	}

	return S_OK;
}

CMediaType *CMiiAudPinIn::MediaType()
{
	return &m_mt;
}

extern void miidx_input_audio(Int8 *pBuffer, UInt32 pts, Int32 size, Int32 sample_rate, Int32 ch, Int32 sb);
static Int32 Resample(Int8 *src, Int32 size, Int32 ch, Int32 fs, Int32 sb, Int8 *dst, Int32 dstlen, Int32 *eated)
{
	Int32 ret;
	Int32 m_ch=1, m_sb=16, m_fs=8000;
	if(ch==m_ch && sb==m_sb && fs==m_fs)
	{
		ret = IMP_MIN(size, dstlen);
		*eated = ret;
		IMP_Memcpy(dst, src, ret);
	}
	else
	{
		Int32 SB = sb>>3;
		Int32 fi = (fs<<10)/m_fs;
		Int32 i, j;
		for(i=0; i<dstlen/(SB*m_ch); i++)
		{
			j = (i*fi)>>10;
			if((j*SB*ch)>=size)
				break;
			for(Int32 n=0; n<SB; n++)
			{
				dst[i*SB*m_ch+n] = src[j*SB*ch+n];
			}
		}
		*eated = j*SB*ch;
		ret = i*SB*m_ch;
	}
	return ret;
}


STDMETHODIMP CMiiAudPinIn::Receive(IMediaSample *pSample)
{
	HRESULT hr;
	char *pBuffer;
	int nLength;
	LONGLONG tstart, tend;
	WAVEFORMATEX  * pvih = 0;
	AM_MEDIA_TYPE  *pmt = 0;
		
	CheckPointer(pSample,E_POINTER);
	if(S_OK == pSample->GetMediaType(&pmt))
	{
		if(pmt->pbFormat){
			pvih = (WAVEFORMATEX *)pmt->pbFormat;
			memcpy(&m_vInfo, pvih, sizeof(m_vInfo));
		}
	}

	hr = pSample->GetPointer((BYTE **)&pBuffer);
	nLength = pSample->GetActualDataLength();

	hr = pSample->GetTime(&tstart, &tend);

	if(hr==S_OK)
	{
		mTimeStamp = tstart/10000;
		static Int8 voice_buffer[4096];
		Int32 eated;
		Int32 size = Resample(pBuffer, nLength, m_vInfo.nChannels, m_vInfo.nSamplesPerSec, m_vInfo.wBitsPerSample, voice_buffer, 4096, &eated);
		Int32 pts = imptimer_get_msticks(0);
		//miidx_input_audio(voice_buffer, mTimeStamp, size, 8000, 1, 16);
		miidx_input_audio(voice_buffer, mTimeStamp, size, 8000, 1, 16);
		Sleep(tend/10000-mTimeStamp);
	}
	return S_OK;
}

STDMETHODIMP CMiiAudPinIn::EndOfStream(void)
{
	return S_OK;
}
